﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Iot.RealTimeData.RealTimeData;
using Iot.RealTimeData.RealTimeDataEvent;
using Iot.Shared.Enums;
using Iot.Shared.Helper;
using Iot.Shared.Path;
using Microsoft.Extensions.Logging;

namespace Iot.RealTimeData;

public sealed class RealTimeDataAll
{
    private readonly IRealTimeData<Enum?, IOnEnumValue> _enum;
    private readonly IRealTimeData<double?, IOnFloatValue> _floating;
    private readonly RealTimeDataInfo _info;
    private readonly IRealTimeData<long?, IOnIntegerValue> _integer;
    private readonly ILogger<RealTimeDataAll> _logger;
    private readonly IRealTimeData<Switching?, IOnSwitchingValue> _switching;

    public RealTimeDataAll(IRealTimeData<double?, IOnFloatValue> floating,
        IRealTimeData<Switching?, IOnSwitchingValue> switching,
        IRealTimeData<Enum?, IOnEnumValue> @enum,
        IRealTimeData<long?, IOnIntegerValue> integer,
        ILogger<RealTimeDataAll> logger,
        RealTimeDataInfo info)
    {
        _floating = floating;
        _switching = switching;
        _enum = @enum;
        _integer = integer;
        _info = info;
        _logger = logger;
        ThreadHelper.RunTask(RunAsync, ThreadPriority.Normal, true, "实时数据过期清理线程开启失败", logger);
    }


    private async Task RunAsync()
    {
        try
        {
            _logger.LogInformation("函数:{函数},线程启动.", nameof(RunAsync));
            var data = new List<IInspection> { _floating, _switching, _enum, _integer };
            using var timer = new PeriodicTimer(_info.Period); //创建定时器

            while (await timer.WaitForNextTickAsync()) //等待下一个定时器触发
            {
                _logger.LogTrace("函数:{函数},定时器触发.", nameof(RunAsync));
                if (timer.Period != _info.Period)
                {
                    timer.Period = _info.Period; //更新定时器周期
                    _logger.LogDebug("函数:{函数},定时器周期更新为:{周期}.", nameof(RunAsync), _info.Period);
                }

                if (!_info.IsEnable || _info.StaleBated <= 0)
                {
                    _logger.LogTrace("函数:{函数},未启用或未设置过期时间,跳过本次循环.", nameof(RunAsync));
                    continue; //如果未启用或未设置过期时间，则跳过
                }

                var staleBated = DateTimeOffset.Now.AddSeconds(-_info.StaleBated); //计算过期时间戳
                _logger.LogTrace("函数:{函数},计算过期时间戳为:{时间戳}.", nameof(RunAsync), staleBated);

                Parallel.ForEach(data, a =>
                {
                    _logger.LogTrace("函数:{函数},执行检查数据.", nameof(RunAsync));
                    a.Inspection(staleBated); //并行检查数据
                });
            }
        }
        catch (Exception e)
        {
            _logger.LogError(e, "函数:{函数},线程运行出错.", nameof(RunAsync));
        }
    }

    /// <summary>
    ///     浮点型数据
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public IFloatValue GetFloatValue(DevicePath path)
    {
        return _floating.GetValue(path);
    }

    /// <summary>
    ///     告警量
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public ISwitchingValue GetSwitchingValue(DevicePath path)
    {
        return _switching.GetValue(path);
    }

    /// <summary>
    ///     枚举
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public IEnumValue GetEnumValue(DevicePath path)
    {
        return _enum.GetValue(path);
    }

    /// <summary>
    ///     整型数据
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public IIntegerValue GetIntegerValue(DevicePath path)
    {
        return _integer.GetValue(path);
    }
}